Bela Lubkin writes: > > Carson Gaspar wrote: > > > Does anyone know what the pt_chmod hole is? The same suid program exists in > > Solaris 2.x, and knowing Sun's track record... > > By my testing, exactly the same bug exists on Solaris 2.3/SPARC; > however, it does not cause a security hole there. The security hole is > caused by how the SCO execution environment treats NULL dereferences. > The same bug probably exists in the pt_chmod source on most System V > systems; whether it causes a security problem depends on how the OS > treats NULL dereferences. > > Full disclosure has been sent to CERT for dissemination to other OS > vendors. I am not in a position to publically disclose full details at > this time; I also think that to do so would be rude to other OS vendors > who have not had a chance to issue their own fixes. > > Your pt_chmod is safe if it coredumps when run as `pt_chmod < > /etc/termcap`. If not, it might or might not be safe. Ask your OS > vendor, "trace" or "truss". > > I'm sorry that I can't say more. > > >Bela< > I had a look at the truss/trace output of pt_chmod on several systems, including a SCO one. Going purely by the truss output (what little there is), it appears that pt_chmod does something approximately like this: main(int argc, char **argv) { chown(ptsname(atoi(argv[1])), getuid(), getgid()); } Note the lack of check for NULL on the return value from ptsname(). Which effectively makes it do a "chown(NULL, your_uid, your_gid)" What happens next depends on what is at memory location zero: Apparently: SCO unix: (char *)NULL = 0000 4c 01 04 00 ce b6 e0 2e b4 35 00 00 fb 01 00 00 L........5...... SVR4: (char *)NULL = ""; 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ I think Solaris has an unmapped page zero, which will cause a core dump. If not, then it's probably the SVR4 case. Fortunately for SVR4 (and probably solaris) systems, the filesystem always returns an "ENOENT" if the user trys to create a file with zero length, so the "chown("", uid, gid)" should never succeed. However, on SCO systems and maybe other SVR3 systems, the chown() can be made to succeed. There. I think there's enough information there to convince people that there's a problem, but there's not enough (I *hope*) for the lamers to wreak havoc with. The "elite" crackers will already have figured this out long ago, as soon as the fix was announced, and would have run trace/truss themselves and figured it out. If you need an exploit script, wait for 8lgm on monday. ***IF YOU HAVE A SCO SYSTEM, INSTALL THE FIX!!!!*** Hmm. something else I though of too. Imagine: root is logged in on /dev/pts/34, and has the tty set to mode 0622. Guess what this would do if you were a normal user: /usr/lib/pt_chmod 1 > /dev/pts/34 You could then TIOCSTI to your hearts content. A plea to OS programmers: *dont* use "chown" on the result of the ptsname() - use fchown() - the user might have passed a fd in that's from a network mounted partition in an attempt to change the ownership of the local alias of the device. Also, RFS makes things interesting too, as the ioctl() in ptsname() is evaluated on the remote machine and returned back. Imagine this: $ ls -l /remotesys/dev/pts/34 crw--w---- 1 joe tty 12, 34 Dec 3 20:34 /remotesys/dev/pts/34 $ ls -l /dev/pts/34 crw--w---- 1 root tty 12, 34 Dec 3 20:34 /dev/pts/34 $ /usr/lib/pt_chmod 0 < /remotesys/dev/pts/34 $ ls -l /dev/pts/34 crw--w---- 1 joe tty 12, 34 Dec 3 20:34 /dev/pts/34 OK. so this is unlikely to be configured this way in a well configured network, and RFS is practically dead.. but you never know what else might turn up in the future as NFS Version 95, or whatever. If you a SYSV derived system, you might like to replace /usr/lib/pt_chmod with something like the code below. No promises that it even works, but at least it should prevent some of the abuse above. Read through it and once you are happy that it wont screw up any more than the standard pt_chmod, make it mode 4111. --------------- /* Copyright (C) 1994, Peter Wemm. All rights reserved. Standard disclaimer: If this doesn't work: tough. If you lose millions because this messes up, it's you that's out the millions, not me. If you don't like this disclaimer: tough. I reserve the right to do the absolute minimum provided by law, up to and including nothing. This is basically the same disclaimer that comes with all software packages, but this is in plain English and theirs is in legalese. I didn't want to include any disclaimer at all, but the lawyers insist. [inspired by Haventrees Software's EasyFlow disclaimer, as posted on usenet] */ #include <sys/types.h> #include <stdio.h> #include <grp.h> #include <unistd.h> #include <fcntl.h> int main(int ac, char **av) { int fd; int gid = getgid(); int uid = getuid(); int mode = 0600; int accmode; struct group *gr; if (ac != 2) exit(255); /* not enough args */ /* look for a secure tty group, and alter the permissions if found */ if ((gr = getgrnam("tty")) != NULL) { gid = gr->gr_gid; /* found protected group 'tty' */ mode = 0620; } else if ((gr = getgrnam("terminal")) != NULL) { gid = gr->gr_gid; /* found protected group 'terminal' */ mode = 0620; } fd = atoi(av[1]); if (ptsname(fd) == NULL) exit(255); /* not a pty */ if ((accmode = fcntl(fd, F_GETFL, 0)) < 0) exit(255); /* paranoid */ if (((accmode & O_ACCMODE) != O_RDONLY) && ((accmode & O_ACCMODE) != O_RDWR)) exit(255); /* not opened in readable mode */ if (fchmod(fd, mode) < 0) exit(255); /* couldn't chmod */ if (fchown(fd, uid, gid) < 0) exit(255); /* couldn't chown */ exit(0); } ------------- Feel free to distribute this wherever and however you like. If you think you can sell it (or a derivative of it) in your OS, go for it and good luck. I only ask for a breif credit in the user-visible man-page for the function that calls pt_chmod, ie: normally where grantpt() is documented. -Peter